/**
 * 防抖函数 - 在事件被触发n秒后再执行回调，如果在这n秒内又被触发，则重新计时
 * @param {Function} fn - 需要防抖的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @param {boolean} immediate - 是否立即执行（第一次触发时立即执行）
 * @returns {Function} 防抖后的函数
 */
export function debounce(fn, delay = 300, immediate = false) {
  let timer = null
  let isInvoked = false

  return function (...args) {
    const context = this

    if (timer) {
      clearTimeout(timer)
    }

    if (immediate && !isInvoked) {
      // 立即执行模式下，第一次触发时立即执行
      fn.apply(context, args)
      isInvoked = true
      timer = setTimeout(() => {
        isInvoked = false
      }, delay)
    } else {
      // 延迟执行模式
      timer = setTimeout(() => {
        fn.apply(context, args)
        isInvoked = false
      }, delay)
    }
  }
}

/**
 * 节流函数 - 规定在一个单位时间内，只能触发一次函数
 * @param {Function} fn - 需要节流的函数
 * @param {number} delay - 节流时间间隔（毫秒）
 * @param {Object} options - 配置选项
 * @param {boolean} options.leading - 是否在开始时立即执行（默认true）
 * @param {boolean} options.trailing - 是否在结束时执行（默认true）
 * @returns {Function} 节流后的函数
 */
export function throttle(fn, delay = 300, options = {}) {
  const { leading = true, trailing = true } = options
  let timer = null
  let lastExecTime = 0
  let lastArgs = null
  let lastContext = null

  const later = () => {
    lastExecTime = leading === false ? 0 : Date.now()
    timer = null
    if (lastArgs) {
      fn.apply(lastContext, lastArgs)
      lastArgs = lastContext = null
    }
  }

  return function (...args) {
    const now = Date.now()
    const context = this

    // 如果是第一次调用且leading为false，则记录当前时间
    if (!lastExecTime && leading === false) {
      lastExecTime = now
    }

    // 计算剩余时间
    const remaining = delay - (now - lastExecTime)

    lastArgs = args
    lastContext = context

    if (remaining <= 0 || remaining > delay) {
      // 可以执行
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      lastExecTime = now
      fn.apply(context, args)
      lastArgs = lastContext = null
    } else if (!timer && trailing !== false) {
      // 设置定时器，在剩余时间后执行
      timer = setTimeout(later, remaining)
    }
  }
}

/**
 * 简单防抖 - 简化版防抖函数，适用于大多数场景
 * @param {Function} fn - 需要防抖的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @returns {Function} 防抖后的函数
 */
export function simpleDebounce(fn, delay = 300) {
  let timer = null
  return function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}

/**
 * 简单节流 - 简化版节流函数，适用于大多数场景
 * @param {Function} fn - 需要节流的函数
 * @param {number} delay - 节流时间间隔（毫秒）
 * @returns {Function} 节流后的函数
 */
export function simpleThrottle(fn, delay = 300) {
  let lastExecTime = 0
  return function (...args) {
    const now = Date.now()
    if (now - lastExecTime >= delay) {
      lastExecTime = now
      fn.apply(this, args)
    }
  }
}

/**
 * 取消防抖/节流 - 创建可取消的防抖函数
 * @param {Function} fn - 需要防抖的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @returns {Object} 包含防抖函数和取消函数的对象
 */
export function cancelableDebounce(fn, delay = 300) {
  let timer = null

  const debouncedFn = function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }

  debouncedFn.cancel = function () {
    clearTimeout(timer)
    timer = null
  }

  return debouncedFn
}

/**
 * 取消节流 - 创建可取消的节流函数
 * @param {Function} fn - 需要节流的函数
 * @param {number} delay - 节流时间间隔（毫秒）
 * @returns {Object} 包含节流函数和取消函数的对象
 */
export function cancelableThrottle(fn, delay = 300) {
  let timer = null
  let lastExecTime = 0

  const throttledFn = function (...args) {
    const now = Date.now()
    if (now - lastExecTime >= delay) {
      lastExecTime = now
      fn.apply(this, args)
    } else if (!timer) {
      timer = setTimeout(() => {
        lastExecTime = Date.now()
        fn.apply(this, args)
        timer = null
      }, delay - (now - lastExecTime))
    }
  }

  throttledFn.cancel = function () {
    clearTimeout(timer)
    timer = null
    lastExecTime = 0
  }

  return throttledFn
}

// 使用示例注释：
/*
// 防抖示例 - 适用于搜索框输入、窗口resize等场景
const handleSearch = debounce((keyword) => {
  console.log('搜索:', keyword)
}, 500)

// 节流示例 - 适用于滚动事件、按钮点击等场景
const handleScroll = throttle(() => {
  console.log('滚动事件')
}, 100)

// 立即执行防抖 - 第一次立即执行，后续防抖
const handleClick = debounce(() => {
  console.log('按钮点击')
}, 1000, true)

// 节流配置选项
const handleMouseMove = throttle(() => {
  console.log('鼠标移动')
}, 50, { leading: true, trailing: false })

// 可取消的防抖
const cancelableSearch = cancelableDebounce((keyword) => {
  console.log('搜索:', keyword)
}, 500)
// 取消执行
cancelableSearch.cancel()
*/
